package com.kamistoat.meimeistore.modulessystem.service.impl;

import com.kamistoat.meimeistore.apisystem.domain.SysUser;
import com.kamistoat.meimeistore.apisystem.entity.SysUserPostEntity;
import com.kamistoat.meimeistore.apisystem.entity.SysUserRoleEntity;
import com.kamistoat.meimeistore.commoncore.constant.UserConstants;
import com.kamistoat.meimeistore.commoncore.exception.ServiceException;
import com.kamistoat.meimeistore.commoncore.utils.StringUtils;
import com.kamistoat.meimeistore.commoncore.utils.bean.BeanUtils;
import com.kamistoat.meimeistore.commoncore.utils.bean.BeanValidators;
import com.kamistoat.meimeistore.commoncore.utils.page.Query;
import com.kamistoat.meimeistore.commonsecurity.utils.SecurityUtils;
import com.kamistoat.meimeistore.modulessystem.dao.SysUserDao;
import com.kamistoat.meimeistore.modulessystem.service.SysConfigService;
import com.kamistoat.meimeistore.modulessystem.service.SysUserPostService;
import com.kamistoat.meimeistore.modulessystem.service.SysUserRoleService;
import com.kamistoat.meimeistore.modulessystem.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kamistoat.meimeistore.commoncore.utils.page.PageUtils;
import com.kamistoat.meimeistore.apisystem.entity.SysUserEntity;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.Validator;


@Service("sysUserService")
public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> implements SysUserService {

    @Autowired
    SysConfigService sysConfigService;
    @Autowired
    SysUserPostService sysUserPostService;
    @Autowired
    SysUserRoleService sysUserRoleService;
    @Autowired
    Validator validator;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SysUserEntity> page = this.page(
                new Query<SysUserEntity>().getPage(params),
                new QueryWrapper<SysUserEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 匹配查询
     */
    @Override
    public List<SysUserEntity> selectUserList(SysUser user) {
        QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("del_flag", UserConstants.USER_NORMAL);
        if (StringUtils.isNotNull(user.getUserId())) {
            queryWrapper.eq("user_id", user.getUserId());
        }
        if (StringUtils.isNotNull(user.getUserName())) {
            queryWrapper.like("user_name", user.getUserName());
        }
        if (StringUtils.isNotNull(user.getStatus())) {
            queryWrapper.eq("status", user.getStatus());
        }
        if (StringUtils.isNotNull(user.getPhonenumber())) {
            queryWrapper.like("phonenumber", user.getPhonenumber());
        }
        if (StringUtils.isNotEmpty((String) user.getParams().get("beginTime"))) {
            queryWrapper.ge("create_time", user.getParams().get("beginTime"));
        }
        if (StringUtils.isNotEmpty((String) user.getParams().get("endTime"))) {
            queryWrapper.le("create_time", user.getParams().get("endTime"));
        }
        if (StringUtils.isNotNull(user.getDeptId())) {
            queryWrapper.eq("dept_id", user.getDeptId());
        }
        // 被DataScope标注，需要携带数据权限参数
        if (StringUtils.isNotEmpty(SecurityUtils.getLoginUser().getAllowedDeptIds())) {
            queryWrapper.in("dept_id", SecurityUtils.getLoginUser().getAllowedDeptIds());
        }
        // 返回结果中不包含密码
        queryWrapper.select(SysUserEntity.class, tableFieldInfo -> !tableFieldInfo.getColumn().equals("password"));
        return this.list(queryWrapper);
    }

    @Override
    public String importUser(List<SysUser> userList, boolean updateSupport, String operName) {
        if (StringUtils.isNull(userList) || userList.size() == 0) {
            throw new ServiceException("导入用户数据不能为空");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        // 为导入的用户设置初始密码
        String password = sysConfigService.selectConfigByKey("sys.user.initPassword");
        for (SysUser user : userList) {
            try {
                // 验证是否存在这个用户
                SysUserEntity one = this.getOne(new QueryWrapper<SysUserEntity>().eq("user_name", user.getUserName()));
                if (StringUtils.isNull(one)) {
                    // 验证数据是否合法
                    BeanValidators.validateWithException(validator, user);
                    user.setPassword(SecurityUtils.encryptPassword(password));
                    user.setCreateBy(operName);
                    // 关联插入
                    insertUser(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 导入成功");
                } else if (updateSupport) {
                    BeanValidators.validateWithException(validator, user);
                    user.setUpdateBy(operName);
                    // 关联更新
                    updateUser(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、账号 " + user.getUserName() + " 已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "共 " + successNum + "条数据导入成功。以下数据导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    /**
     * 关联插入用户。为保证关联正确，需使用事务
     * 回滚触发机制为 发生Exception(及其子类)
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean insertUser(SysUser sysUser) {
        SysUserEntity sysUserEntity = new SysUserEntity();
        BeanUtils.copyProperties(sysUser, sysUserEntity);
        boolean saveUser = this.save(sysUserEntity);
        boolean savePost = insertUserPost(sysUser);
        boolean saveRole = insertUserRole(sysUser);
        return saveUser && savePost && saveRole;
    }

    /**
     * 关联更新用户。为保证正确，需要使用事务
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUser(SysUser sysUser) {
        SysUserEntity sysUserEntity = new SysUserEntity();
        BeanUtils.copyProperties(sysUser, sysUserEntity);

        int updateUser = this.getBaseMapper().updateBaseMessage(sysUser);

        // 删除原本的用户岗位关联
        // 用BaseMapper的detele是因为mybatis的remove在删除记录为0时会返回false，影响后序判断
        int deletePost =
                sysUserPostService.getBaseMapper().delete(
                        new QueryWrapper<SysUserPostEntity>().eq("user_id", sysUser.getUserId()));
        // 重新插入用户岗位关联
        boolean savePost = insertUserPost(sysUser);
        // 删除原本的用户角色关联
        int deleteRole =
                sysUserRoleService.getBaseMapper().delete(
                        new QueryWrapper<SysUserRoleEntity>().eq("user_id", sysUser.getUserId()));
        // 重新插入用户角色关联
        boolean saveRole = insertUserRole(sysUser);
        return (updateUser == 1) && (deletePost >= 0) && savePost && (deleteRole >= 0) && saveRole;
    }

    /**
     * 检查用户名是否已经存在。同时考虑新增和修改两种情况。
     */
    @Override
    public boolean checkUserNameUnique(SysUser sysUser) {
        SysUserEntity one = this.getOne(
                new QueryWrapper<SysUserEntity>().eq("user_name", sysUser.getUserName()));
        return StringUtils.isNotNull(one) && !one.getUserId().equals(sysUser.getUserId());
    }

    /**
     * 检查手机号是否已存在。
     *
     * @param sysUser
     */
    @Override
    public boolean checkPhoneUnique(SysUser sysUser) {
        SysUserEntity one = this.getOne(
                new QueryWrapper<SysUserEntity>().eq("phonenumber", sysUser.getPhonenumber()));
        return StringUtils.isNotNull(one) && !one.getUserId().equals(sysUser.getUserId());
    }

    /**
     * 检查邮箱是否已存在。
     *
     * @param sysUser
     */
    @Override
    public boolean checkEmailUnique(SysUser sysUser) {
        SysUserEntity one = this.getOne(
                new QueryWrapper<SysUserEntity>().eq("email", sysUser.getEmail()));
        return StringUtils.isNotNull(one) && !one.getUserId().equals(sysUser.getUserId());
    }

    /**
     * 为用户添加角色
     */
    @Override
    public boolean insertUserAuthRole(Long userId, Long[] roleIds) {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setRoleIds(roleIds);
        return insertUserRole(sysUser);
    }

    /**
     * 为用户添加岗位
     */
    @Override
    public boolean insertUserAuthPost(Long userId, Long[] postIds) {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setPostIds(postIds);
        return insertUserPost(sysUser);
    }

    /**
     * 插入用户和岗位关联
     */
    private boolean insertUserPost(SysUser sysUser) {
        Long[] postIds = sysUser.getPostIds();
        try {
            if (StringUtils.isNotNull(postIds) && postIds.length > 0) {
                // 新增用户与岗位管理
                List<SysUserPostEntity> upList = new ArrayList<SysUserPostEntity>();
                for (Long postId : postIds) {
                    SysUserPostEntity up = new SysUserPostEntity();
                    up.setUserId(sysUser.getUserId());
                    up.setPostId(postId);
                    upList.add(up);
                }
                return sysUserPostService.saveBatch(upList);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 插入用户和角色关联
     */
    private boolean insertUserRole(SysUser sysUser) {
        Long[] roleIds = sysUser.getRoleIds();
        try {
            if (StringUtils.isNotNull(roleIds) && roleIds.length > 0) {
                // 新增用户与岗位管理
                List<SysUserRoleEntity> upList = new ArrayList<>();
                for (Long roleId : roleIds) {
                    SysUserRoleEntity up = new SysUserRoleEntity();
                    up.setUserId(sysUser.getUserId());
                    up.setRoleId(roleId);
                    upList.add(up);
                }
                return sysUserRoleService.saveBatch(upList);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

}
